package com.dom.domweb.modular.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dom.common.constants.Constants;
import com.dom.common.exception.ServiceException;
import com.dom.common.model.vo.basic.*;
import com.dom.domweb.common.RspModel;
import com.dom.domweb.dao.entity.TClientContInfo;
import com.dom.domweb.dao.entity.TClientInfo;
import com.dom.domweb.dao.entity.TSysCodeTbl;
import com.dom.domweb.dao.service.ITClientContInfoService;
import com.dom.domweb.dao.service.ITClientInfoService;
import com.dom.domweb.dao.service.ITSysCodeTblService;
import com.xiaoleilu.hutool.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class ClientInfoService extends AbstractApproveService {

    @Autowired
    private ITClientInfoService clientInfoService;
    @Autowired
    private ITClientContInfoService clientContInfoService;
    @Autowired
    private ITSysCodeTblService sysCodeTblService;

    public B029A findCustInfoList(B029R request) {
        Wrapper<TClientInfo> wrapper = new EntityWrapper<TClientInfo>();
        Page<TClientInfo> page = new Page<TClientInfo>();
        page.setSize(request.getPs() == 0 ? 20 : request.getPs());
        page.setCurrent(request.getPn());
        if (StringUtils.isNotEmpty(request.getAbbrName())){
            wrapper.like("abbr_name",request.getAbbrName());
        }
        if (StringUtils.isNotEmpty(request.getOrganLicense())){
            wrapper.and().eq("organ_license",request.getOrganLicense());
        }
        List<String> orderList = new ArrayList<String>();
        orderList.add("due_date");
        orderList.add("ctime");
        wrapper.orderBy(true,orderList,false);
        Page<TClientInfo> pages = clientInfoService.selectPage(page,wrapper);
        B029A result = pageToInfo(pages.getRecords());
        return result;
    }

    public Map<String,Object> getAllClientInfoToMap(){
        Wrapper<TClientInfo> wrapper = new EntityWrapper<TClientInfo>();
        List<TClientInfo> list = clientInfoService.selectList(wrapper);
        Map<String,Object> map = new HashMap<String,Object>();
        for (TClientInfo info: list ) {
            map.put(info.getCustCode().toString(),info.getAbbrName());
        }
        return map;
    }

    private B029A pageToInfo(List<TClientInfo> records) {
        B029A result = new B029A();
        Map<String,String> certType = getCertTypeToMap();
        Map<String,String> custType = getCustTypeToMap();
        Map<String,String> level = getCustLevelToMap();
        List<CustInfo> list = new ArrayList<CustInfo>();
        for (TClientInfo info: records ) {
            CustInfo cust = clientToCust(info,certType,custType,level);
            list.add(cust);
        }
        result.setCustInfoData(list);
        return result;
    }

    private Map<String,String> getCertTypeToMap(){
        List<TSysCodeTbl> list = sysCodeTblService.findSysCode(Constants.CERT_TYPE_SYS_CODE);
        Map<String,String> map = new HashMap<>();
        for (TSysCodeTbl tbl: list) {
            map.put(tbl.getSysValue(),tbl.getCodeDesc());
        }
        return map;
    }

    private Map<String,String> getCustTypeToMap(){
        List<TSysCodeTbl> list = sysCodeTblService.findSysCode(Constants.CUST_TYPE_SYS_CODE);
        Map<String,String> map = new HashMap<>();
        for (TSysCodeTbl tbl: list) {
            map.put(tbl.getSysValue(),tbl.getCodeDesc());
        }
        return map;
    }

    private Map<String,String> getCustLevelToMap(){
        List<TSysCodeTbl> list = sysCodeTblService.findSysCode(Constants.CUST_LEVEL_SYS_CODE);
        Map<String,String> map = new HashMap<>();
        for (TSysCodeTbl tbl: list) {
            map.put(tbl.getSysValue(),tbl.getCodeDesc());
        }
        return map;
    }

    public RspModel insertCustInfo(B020R request) {
        TClientInfo info = beanToInfo(request);
        Wrapper<TClientInfo> wrap = new EntityWrapper<TClientInfo>();
        wrap.eq("cust_code",info.getCustCode());
        TClientInfo client = clientInfoService.selectOne(wrap);
        if (client != null){
            return new RspModel("RSP00036","该客户代码已经存在！");
        }
        boolean isTrue = clientInfoService.insert(info);
        if(!isTrue){
            log.info("客户信息新增失败, result:{}", isTrue);
            throw new ServiceException("9001", "客户信息新增数据库异常");
        }

        List<TClientContInfo> list = new ArrayList<>();
        for (CustLinkInfo cust:request.getCustLinkData() ) {
            TClientContInfo contInfo = beanToCont(cust,info);
            list.add(contInfo);
        }
        isTrue = clientContInfoService.insertBatch(list);
        if(!isTrue){
            log.info("客户联系人信息新增失败, result:{}", isTrue);
            throw new ServiceException("9001", "客户联系人信息新增数据库异常");
        }
        return new RspModel(info.getId().toString());
    }

    private TClientContInfo beanToCont(CustLinkInfo cust,TClientInfo client){
        TClientContInfo info = new TClientContInfo();
        info.setContId(client.getId());
        info.setContName(cust.getContName());
        info.setContPhone(cust.getContPhone());
        info.setContSex(cust.getContSex());
        info.setLevel(StringUtils.isEmpty(cust.getLevel()) ? null : Integer.valueOf(cust.getLevel()));
        info.setCustCode(client.getCustCode());
        info.setMemCode(client.getMemCode());
        info.setVersion(0);
        return info;
    }

    private CustInfo clientToCust(TClientInfo info, Map<String,String> certType, Map<String,String> custType, Map<String,String> custLevel){
        CustInfo cust = new CustInfo();
        cust.setId(info.getId().toString());
        cust.setAbbrName(info.getAbbrName());
        cust.setAddress(info.getAddress());
        cust.setCertNo(info.getCertNo());
        cust.setMemCode(info.getMemCode() == null ? null : info.getMemCode().toString());
        cust.setCertType(info.getCertType() == null ? null : info.getCertType().toString());
        cust.setCertTypeDesc(info.getCertType() == null ? null : certType.get(info.getCertType().toString()));
        cust.setCustCode(info.getCustCode() == null ? null : info.getCustCode().toString());
        cust.setCustLevel(info.getCustLevel() == null ? null : info.getCustLevel().toString());
        cust.setCustTypeDesc(info.getCustType() == null ? null : custType.get(info.getCustType().toString()));
        cust.setCustType(info.getCustType() == null ? null : info.getCustType().toString());
        cust.setCustLevelDesc(info.getCustLevel() == null ? null : custLevel.get(info.getCustLevel().toString()));
        cust.setCustName(info.getCustName());
        cust.setDueDate(info.getDueDate() == null ? null : DateUtil.formatDate(info.getDueDate()));
        cust.setLegalName(info.getLegalName());
        cust.setOrganLicense(info.getOrganLicense());
        cust.setCtime(info.getCtime() == null ? null : DateUtil.formatDate(info.getCtime()));
        return cust;
    }

    private TClientInfo beanToInfo(B020R request){
        TClientInfo info = new TClientInfo();
        info.setAbbrName(request.getAbbrName());
        info.setAddress(request.getAddress());
        info.setCertNo(request.getCertNo());
        info.setCertType(StringUtils.isEmpty(request.getCertType()) ? null : Integer.valueOf(request.getCertType()));
        info.setCustCode(StringUtils.isEmpty(request.getCustCode()) ? null : Integer.valueOf(request.getCustCode()));
        info.setCustLevel(StringUtils.isEmpty(request.getCustLevel()) ? null : Integer.valueOf(request.getCustLevel()));
        info.setCustName(request.getCustName());
        info.setCustType(StringUtils.isEmpty(request.getCustType()) ? null : Integer.valueOf(request.getCustType()));
        info.setDueDate(StringUtils.isEmpty(request.getDueDate()) ? null : DateUtil.parseDate(request.getDueDate()));
        info.setLegalName(request.getLegalName());
        info.setOrganLicense(request.getOrganLicense());
        info.setVersion(0);
        info.setMemCode(0);
        return info;
    }

    public B023A findUpdateCustInfoPage(String id) {
        Wrapper<TClientContInfo> wrapper = new EntityWrapper<TClientContInfo>();
        TClientInfo client = clientInfoService.selectById(id);
        B023A result = clientToResult(client);
        wrapper.eq("cont_id",id);
        List<CustLinkInfo> linkList = new ArrayList<CustLinkInfo>();
        List<TClientContInfo> list = clientContInfoService.selectList(wrapper);
        for (TClientContInfo cont: list) {
            CustLinkInfo info = contTolink(cont);
            linkList.add(info);
        }
        result.setCustLinkData(linkList);
        return result;
    }

    public List<CustInfo> getAllClientInfo(){
        Wrapper<TClientInfo> wrapper = new EntityWrapper<TClientInfo>();
        List<TClientInfo> list = clientInfoService.selectList(wrapper);
        List<CustInfo> custList = new ArrayList<CustInfo>();
        Map<String,String> certType = getCertTypeToMap();
        Map<String,String> custType = getCustTypeToMap();
        Map<String,String> custLevel = getCustLevelToMap();
        for (TClientInfo client:list) {
            CustInfo cust = clientToCust(client,certType,custType,custLevel);
            custList.add(cust);
        }
        return custList;
    }

    private CustLinkInfo contTolink(TClientContInfo cont){
        CustLinkInfo info = new CustLinkInfo();
        info.setContName(cont.getContName());
        info.setContPhone(cont.getContPhone());
        info.setLevel(cont.getLevel() == null ? null : cont.getLevel().toString());
        info.setContSex(cont.getContSex());
        info.setCustCode(cont.getCustCode());
        info.setId(cont.getId().toString());
        info.setMemCode(cont.getMemCode());
        return info;
    }

    private B023A clientToResult(TClientInfo client){
        B023A result = new B023A();
        result.setId(client.getId().toString());
        result.setAbbrName(client.getAbbrName());
        result.setAddress(client.getAddress());
        result.setCertNo(client.getCertNo());
        result.setCertType(client.getCertType() == null ? null : client.getCertType().toString());
        result.setCertTypeDesc(client.getCertType() == null ? null : client.getCertType().toString());
        result.setCustCode(client.getCustCode() == null ? null : client.getCustCode().toString());
        result.setCustLevel(client.getCustLevel() == null ? null : client.getCustLevel().toString());
        result.setCustTypeDesc(client.getCustType() == null ? null : client.getCustType().toString());
        result.setCustType(client.getCustType() == null ? null : client.getCustType().toString());
        result.setCustName(client.getCustName());
        result.setDueDate(client.getDueDate() == null ? null : DateUtil.formatDate(client.getDueDate()));
        result.setLegalName(client.getLegalName());
        result.setOrganLicense(client.getOrganLicense());
        return result;
    }

    public boolean custInfoDel(String id) {
        Wrapper<TClientContInfo> wrapper = new EntityWrapper<TClientContInfo>();

        boolean isTrue = clientInfoService.deleteById(Integer.valueOf(id));
        if(!isTrue){
            log.info("客户信息删除失败, result:{}", isTrue);
            throw new ServiceException("9001", "客户信息删除数据库异常");
        }
        wrapper.eq("cont_id",id);
        isTrue = clientContInfoService.delete(wrapper);
        if(!isTrue){
            log.info("客户联系人信息删除失败, result:{}", isTrue);
            throw new ServiceException("9001", "客户联系人信息删除数据库异常");
        }
        return isTrue;
    }

    public RspModel custInfoModify(B022R request) {
        Wrapper<TClientContInfo> contWrapper = new EntityWrapper<TClientContInfo>();
        TClientInfo info = modifyToClient(request);
        boolean isTrue = clientInfoService.updateById(info);
        if(!isTrue){
            log.info("客户信息修改失败, result:{}", isTrue);
            return new RspModel("RSP000003", "客户信息修改数据库异常");
        }
        List<String> list = new ArrayList<>();
        if (request.getCustLinkData() != null && request.getCustLinkData().size() != 0){
            for (B032R link : request.getCustLinkData() ) {
                if (StringUtils.isNotEmpty(link.getKeyId())){
                    list.add(link.getKeyId());
                }
            }
        }
        contWrapper.notIn("id",list);
        contWrapper.eq("cont_id",request.getId());
        isTrue = clientContInfoService.delete(contWrapper);
        if(!isTrue){
            log.info("客户联系人信息修改失败, result:{}", isTrue);
            return new RspModel("RSP000002", "客户联系人信息修改数据库异常");
        }
        List<String> contIdList = clientContInfoService.selectContIdByCustId(request.getId());
        for (B032R detail : request.getCustLinkData()) {
            TClientContInfo detailFlow = toCont(detail, request);
            if (!StringUtils.isEmpty(detail.getKeyId()) &&
                    contIdList.contains(detail.getKeyId())) {
                Wrapper<TClientContInfo> detailIdWap = new EntityWrapper<TClientContInfo>();
                detailIdWap.and().eq("id", detail.getKeyId());
                clientContInfoService.update(detailFlow, detailIdWap);
            } else {
                clientContInfoService.insert(detailFlow);
            }
        }
        return new RspModel("RSP000000","客户信息修改成功！");
    }

    private TClientContInfo toCont(B032R detail, B022R request) {
        TClientContInfo info = new TClientContInfo();
        info.setId(StringUtils.isEmpty(detail.getKeyId()) ? null : Integer.valueOf(detail.getKeyId()));
        info.setContId(Integer.valueOf(request.getId()));
        info.setContName(detail.getContName());
        info.setContPhone(detail.getContPhone());
        info.setContSex(detail.getContSex());
        info.setLevel(detail.getLevel());
        info.setCustCode(detail.getCustCode());
        info.setMemCode(request.getMemCode() == null ? 0 : request.getMemCode());
        info.setVersion(0);
        return info;
    }

    private TClientInfo modifyToClient(B022R request){
        TClientInfo info = new TClientInfo();
        info.setId(StringUtils.isEmpty(request.getId()) ? null : Integer.valueOf(request.getId()));
        info.setAbbrName(request.getAbbrName());
        info.setAddress(request.getAddress());
        info.setCertNo(request.getCertNo());
        info.setCertType(StringUtils.isEmpty(request.getCertType()) ? null : Integer.valueOf(request.getCertType()));
        info.setCustCode(StringUtils.isEmpty(request.getCustCode()) ? null : Integer.valueOf(request.getCustCode()));
        info.setCustLevel(StringUtils.isEmpty(request.getCustLevel()) ? null : Integer.valueOf(request.getCustLevel()));
        info.setCustName(request.getCustName());
        info.setCustType(StringUtils.isEmpty(request.getCustType()) ? null : Integer.valueOf(request.getCustType()));
        info.setDueDate(StringUtils.isEmpty(request.getDueDate()) ? null : DateUtil.parseDate(request.getDueDate()));
        info.setLegalName(request.getLegalName());
        info.setOrganLicense(request.getOrganLicense());
        return info;
    }

    public B023A findContInfo(String custCode) {
        Wrapper<TClientContInfo> wrapper = new EntityWrapper<TClientContInfo>();
        Wrapper<TClientInfo> wrap = new EntityWrapper<TClientInfo>();
        wrapper.eq("cust_code",custCode);
        wrap.eq("cust_code",custCode);
        TClientInfo client = clientInfoService.selectOne(wrap);
        B023A result = clientToResult(client);
        List<CustLinkInfo> linkList = new ArrayList<CustLinkInfo>();
        List<TClientContInfo> list = clientContInfoService.selectList(wrapper);
        for (TClientContInfo cont: list) {
            CustLinkInfo info = contTolink(cont);
            linkList.add(info);
        }
        result.setCustLinkData(linkList);
        return result;
    }

    public CustLinkInfo findContInfoById(String id) {
        Wrapper<TClientContInfo> wrapper = new EntityWrapper<TClientContInfo>();
        wrapper.eq("id",id);
        TClientContInfo result = clientContInfoService.selectById(id);
        CustLinkInfo info = contTolink(result);
        return info;
    }
}
